using System;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.Ccr.Core;
using Microsoft.Dss.Core.Attributes;
using Microsoft.Dss.ServiceModel.Dssp;
using Microsoft.Dss.ServiceModel.DsspServiceBase;
using W3C.Soap;

using vision = HCC.Robotics.HCCSimpleVisionModule;

namespace HCC.Robotics.HCCSimpleVisionModule
{
    /// <summary>
    /// HCCSimpleVisionModule contract class
    /// </summary>
    public sealed class Contract
    {
        /// <summary>
        /// DSS contract identifer for HCCSimpleVisionModule
        /// </summary>
        [DataMember]
        public const string Identifier = "http://www.hccrobotica.nl/2011/09/hccsimplevisionmodule.html";
    }

    /// <summary>
    /// HCCSimpleVisionModule state
    /// </summary>
    [DataContract]
    public class HCCSimpleVisionModuleState
    {
        /// <summary>
        /// Image Width
        /// </summary>
        [DataMember]
        [Description("Specifies the image width.")]
        public const int ImageWidth = 640;
        /// <summary>
        /// Image Height
        /// </summary>
        [DataMember]
        [Description("Specifies the image height.")]
        public const int ImageHeight = 480;
        /// <summary>
        /// Max Regions for segmentation
        /// </summary>
        [DataMember]
        [Description("Specifies maximum number of regions for segmentation.")]
        public const int MaxRegions = 100; //IT4
        /// <summary>
        /// Max Bots that will be tracked
        /// </summary>
        [DataMember]
        [Description("Specifies maximum number of bots to be tracked.")]
        public const int MaxBotTracks = 6; //IT

        /// <summary>
        /// WebCam PollingInterval In Ms
        /// </summary>
        [DataMember]
        [Description("Indicates the polling interval for the webcam service (in ms).")]
        public int WebCamPollingIntervalInMs;

        /// <summary>
        /// ColorVector of Tracking Object Color
        /// </summary>
        [DataMember]
        [Description("Specifies the color to be tracked (RGB and similarity threshold).")]
        public ColorVector TrackingObjectColorBall;
        /// <summary>
        /// ColorVector of Tracking Object Color
        /// </summary>
        [DataMember]
        [Description("Specifies the color to be tracked (RGB and similarity threshold).")]
        public ColorVector TrackingObjectColorYellow;
        /// <summary>
        /// ColorVector of Tracking Object Color
        /// </summary>
        [DataMember]
        [Description("Specifies the color to be tracked (RGB and similarity threshold).")]
        public ColorVector TrackingObjectColorBlue;
        /// <summary>
        /// ColorVector of Tracking Object Color
        /// </summary>
        [DataMember]
        [Description("Specifies the color to be tracked (RGB and similarity threshold).")]
        public ColorVector TrackingObjectColorPink;

        /// <summary>
        /// AreaThreshold of Color Object detection
        /// </summary>
        [DataMember]
        [Description("Specifies the color object detection area threshold (minimum number of pixels).\n(Default value = 200, typical range = 50-5000)")]
        public int ColorAreaThreshold;

        /// <summary>
        /// Current Object Detection Result
        /// </summary>
        public ObjectResult CurObjectResult;
    }

    /// <summary>
    /// HCCSimpleVisionModule main operations port
    /// </summary>
    [ServicePort]
    public class HCCSimpleVisionModuleOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Get, Subscribe, SetObjectTrackingColor, UpdateFieldMeasures, NotifyObjectDetection>
    {
    }

    /// <summary>
    /// HCCSimpleVisionModule get operation
    /// </summary>
    public class Get : Get<GetRequestType, PortSet<HCCSimpleVisionModuleState, Fault>>
    {
        /// <summary>
        /// Creates a new instance of Get
        /// </summary>
        public Get()
        {
        }

        /// <summary>
        /// Creates a new instance of Get
        /// </summary>
        /// <param name="body">the request message body</param>
        public Get(GetRequestType body)
            : base(body)
        {
        }

        /// <summary>
        /// Creates a new instance of Get
        /// </summary>
        /// <param name="body">the request message body</param>
        /// <param name="responsePort">the response port for the request</param>
        public Get(GetRequestType body, PortSet<HCCSimpleVisionModuleState, Fault> responsePort)
            : base(body, responsePort)
        {
        }
    }

    /// <summary>
    /// HCCSimpleVisionModule subscribe operation
    /// </summary>
    public class Subscribe : Subscribe<SubscribeRequestType, PortSet<SubscribeResponseType, Fault>>
    {
        /// <summary>
        /// Creates a new instance of Subscribe
        /// </summary>
        public Subscribe()
        {
        }

        /// <summary>
        /// Creates a new instance of Subscribe
        /// </summary>
        /// <param name="body">the request message body</param>
        public Subscribe(SubscribeRequestType body)
            : base(body)
        {
        }

        /// <summary>
        /// Creates a new instance of Subscribe
        /// </summary>
        /// <param name="body">the request message body</param>
        /// <param name="responsePort">the response port for the request</param>
        public Subscribe(SubscribeRequestType body, PortSet<SubscribeResponseType, Fault> responsePort)
            : base(body, responsePort)
        {
        }
    }

    /// <summary>
    /// UpdateObjectColor Operation
    /// </summary>
    [Description("Sets the object tracking color.")]
    public class SetObjectTrackingColor : Update<ColorVector, PortSet<DefaultUpdateResponseType, Fault>>
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public SetObjectTrackingColor()
        {
        }
        /// <summary>
        /// Constructor with ColorVector
        /// </summary>
        public SetObjectTrackingColor(ColorVector body)
            : base(body)
        {
        }
    }
    /// <summary>
    /// UpdateFieldMeasures Operation
    /// </summary>
    [Description("Updates the measures of the field.")]
    public class UpdateFieldMeasures : Update<FieldMeasures, PortSet<DefaultUpdateResponseType, Fault>>
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public UpdateFieldMeasures()
        {
        }
        /// <summary>
        /// Constructor with ColorVector
        /// </summary>
        public UpdateFieldMeasures(FieldMeasures body)
            : base(body)
        {
        }
    }

    /// <summary>
    /// ObjectDetection Operation
    /// </summary>
    [DisplayName("DetectColoredObject")]
    [Description("Indicates that a colored object has been detected.")]
    public class NotifyObjectDetection : Update<ObjectResult, PortSet<DefaultUpdateResponseType, Fault>>
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public NotifyObjectDetection()
        {
        }
        /// <summary>
        /// Constructor with ObjectResult
        /// </summary>
        public NotifyObjectDetection(ObjectResult body)
            : base(body)
        {
        }
    }

    /// <summary>
    /// ColorVector for color feature description
    /// </summary>
    [DataContract]
    public class ColorVector
    {
        [DataContract]
        public enum TrackingColor
        {
            Ball,
            Yellow,
            Blue,
            Pink,
            None
        }
        /// <summary>
        /// Name of the ColorVector
        /// </summary>
        [Description("The Name this ColorVector represents")]
        [DataMember]
        public TrackingColor Name;
        /// <summary>
        /// Normalized Red Component
        /// </summary>
        [Description("Indicates the normalized Red value = Red/(Red+Green+Blue).\n(Range = 0.0-1.0)")]
        [DataMember]
        public double Red;
        /// <summary>
        /// Normalized Green Component
        /// </summary>
        [Description("Indicates the normalized Green value = Green/(Red+Green+Blue).\n(Range = 0.0-1.0)")]
        [DataMember]
        public double Green;
        /// <summary>
        /// Normalized Blue Component
        /// </summary>
        [Description("Indicates the normalized Blue value = Blue/(Red+Green+Blue).\n(Range = 0.0-1.0)")]
        [DataMember]
        public double Blue;

        /// <summary>
        /// Similarity Threshold Value
        /// </summary>
        [Description("Indicates the similarity threshold value; comparing two color vectors.\n(Typical range = 0.9~1.0)")]
        [DataMember]
        public double SimilarityMeasure;

        /// <summary>
        /// Constructor
        /// </summary>
        public ColorVector()
        {
            SimilarityMeasure = 0.993;
        }
        /// <summary>
        /// Constructor with red, green
        /// </summary>
        public ColorVector(double red, double green)
        {
            Red = red;
            Green = green;
            SimilarityMeasure = 0.993;
        }
        /// <summary>
        /// Constructor with red, green, blue
        /// </summary>
        public ColorVector(TrackingColor name, double red, double green, double blue)
        {
            Name = name;
            Red = red;
            Green = green;
            Blue = blue;
            SimilarityMeasure = 0.993;
        }
        /// <summary>
        /// Constructor with red, green, blue, similarity
        /// </summary>
        public ColorVector(TrackingColor name, double red, double green, double blue, double similarity)
        {
            Name = name;
            Red = red;
            Green = green;
            Blue = blue;
            SimilarityMeasure = similarity;
        }
        /// <summary>
        /// Return the Magnitude of the vector
        /// </summary>
        public double Magnitude()
        {
            return Math.Sqrt(Red * Red + Green * Green + Blue * Blue);
        }
        /// <summary>
        /// Return the Dot Product of two Vectors
        /// </summary>
        public static double DotProduct(ColorVector cv1, ColorVector cv2)
        {
            if (cv1 == null)
                return 0;
            if (cv2 == null)
                return 0;

            return (cv1.Red * cv2.Red) + (cv1.Green * cv2.Green) + (cv1.Blue * cv2.Blue);
        }
        /// <summary>
        /// Calculate the similarity between two color vectors
        /// </summary>
        public static double CompareSimilarity(ColorVector cv1, ColorVector cv2)
        {
            if (cv1 == null)
                return 0;
            if (cv2 == null)
                return 0;

            double mag = (cv1.Magnitude() * cv2.Magnitude());
            if (mag != 0)
                return (DotProduct(cv1, cv2) / mag);
            return 0;
        }
    }

    [DataContract]
    public class FieldMeasures
    {
        [DataMember]
        public DateTime TimeStamp { get; set; }

        // Field Data
        [DataMember]
        public int TopLeftX { get; set; }
        [DataMember]
        public int TopRightX { get; set; }
        [DataMember]
        public int BottomLeftX { get; set; }
        [DataMember]
        public int BottomRightX { get; set; }
        [DataMember]
        public int LeftGoalUpperX { get; set; }
        [DataMember]
        public int LeftGoalLowerX { get; set; }
        [DataMember]
        public int RightGoalUpperX { get; set; }
        [DataMember]
        public int RightGoalLowerX { get; set; }
        [DataMember]
        public int TopLeftY { get; set; }
        [DataMember]
        public int TopRightY { get; set; }
        [DataMember]
        public int BottomLeftY { get; set; }
        [DataMember]
        public int BottomRightY { get; set; }
        [DataMember]
        public int LeftGoalUpperY { get; set; }
        [DataMember]
        public int LeftGoalLowerY { get; set; }
        [DataMember]
        public int RightGoalUpperY { get; set; }
        [DataMember]
        public int RightGoalLowerY { get; set; }
        
        /// <summary>
        /// Constructor
        /// </summary>
        public FieldMeasures()
        {
        }
    }

    /// <summary>
    /// Color Object Detection Result
    /// </summary>
    [DataContract]
    public class ObjectResult
    {

        /// <summary>
        /// Object Found flag
        /// </summary>
        [DataMember]
        [Description("Indicates a color object was found.")]
        public bool ObjectFound;
        /// <summary>
        /// X Mean
        /// </summary>
        [DataMember]
        [Description("Indicates the color object's X mean value.")]
        public int XMean;
        /// <summary>
        /// Y Mean
        /// </summary>
        [DataMember]
        [Description("Indicates the color object's Y mean value.")]
        public int YMean;
        /// <summary>
        /// Object Area
        /// </summary>
        [DataMember]
        [Description("Indicates the color object's area.")]
        public int Area;
        /// <summary>
        /// X StdDev
        /// </summary>
        [DataMember]
        [Description("Indicates the color object's X standard deviation value.")]
        public double XStdDev;
        /// <summary>
        /// Y StdDev
        /// </summary>
        [DataMember]
        [Description("Indicates the color object's Y standard deviation value.")]
        public double YStdDev;

        /// <summary>
        /// Motion Found flag
        /// </summary>
        [DataMember]
        [Description("Indicates object moved.")]
        public bool MotionFound;
        /// <summary>
        /// X Motion
        /// </summary>
        [DataMember]
        [Description("Indicates object movement in the X direction.")]
        public int XMotion;
        /// <summary>
        /// Y Motion
        /// </summary>
        [DataMember]
        [Description("Indicates object movement in the Y direction.")]
        public int YMotion;
        /// <summary>
        /// Motion Size
        /// </summary>
        [DataMember]
        [Description("Indicates size of the object movement.")]
        public int MotionSize;

        /// <summary>
        /// Constructor
        /// </summary>
        public ObjectResult()
        {
        }
        /// <summary>
        /// Constructor with ImageProcessingResult
        /// </summary>
        public ObjectResult(ImageProcessingResult[] result)
        {
            if (result == null)
                return;
            //IT3 ObjectFound = result.ObjectFound;
            //XMean = result.XMean;
            //YMean = result.YMean;
            //Area = result.Area;
            //XStdDev = result.XStdDev;
            //YStdDev = result.YStdDev;

            //MotionFound = result.MotionFound;
            //XMotion = result.XMotion;
            //YMotion = result.YMotion;
            //MotionSize = result.MotionSize;
        }
    }

    /// <summary>
    /// PointType struct
    /// </summary>
    [DataContract]
    public struct PointType
    {
        /// <summary>
        /// x point
        /// </summary>
        public int x;
        /// <summary>
        /// y point
        /// </summary>
        public int y;

        /// <summary>
        /// GetHashCode
        /// </summary>
        public override int GetHashCode()
        {
            return x ^ y;
        }
        /// <summary>
        /// Equals
        /// </summary>
        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (this.GetType() != obj.GetType()) return false;
            // safe because of the GetType check
            PointType cust = (PointType)obj;
            if (cust.x != x || cust.y != y) return false;
            return true;
        }
        /// <summary>
        /// operator ==
        /// </summary>
        public static bool operator ==(PointType point1, PointType point2) { return point1.Equals(point2); }
        /// <summary>
        /// operator !=
        /// </summary>
        public static bool operator !=(PointType point1, PointType point2) { return !point1.Equals(point2); }
    }

    /// <summary>
    /// RectangleType struct
    /// </summary>
    [DataContract]
    public struct RectangleType
    {
        /// <summary>
        /// left
        /// </summary>
        public int Sx;
        /// <summary>
        /// top
        /// </summary>
        public int Sy;
        /// <summary>
        /// right
        /// </summary>
        public int Ex;
        /// <summary>
        /// bottom
        /// </summary>
        public int Ey;

        /// <summary>
        /// Constructor
        /// </summary>
        public RectangleType(int sx, int sy, int ex, int ey)
        {
            Sx = sx;
            Sy = sy;
            Ex = ex;
            Ey = ey;
        }
        /// <summary>
        /// GetHashCode
        /// </summary>
        public override int GetHashCode()
        {
            return Sx ^ Sy ^ Ex ^ Ey;
        }
        /// <summary>
        /// Equals
        /// </summary>
        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (this.GetType() != obj.GetType()) return false;
            // safe because of the GetType check
            RectangleType cust = (RectangleType)obj;
            if (cust.Sx != Sx || cust.Sy != Sy || cust.Ex != Ex || cust.Ey != Ey) return false;
            return true;
        }
        /// <summary>
        /// operator ==
        /// </summary>
        public static bool operator ==(RectangleType point1, RectangleType point2) { return point1.Equals(point2); }
        /// <summary>
        /// operator !=
        /// </summary>
        public static bool operator !=(RectangleType point1, RectangleType point2) { return !point1.Equals(point2); }
    }
    /// <summary>
    /// RectangleType struct
    /// </summary>
    [DataContract]
    public struct BotTracksType
    {
        ///<summary>
        ///BotNumber
        ///</summary>
        public int BotNumber;
        /// <summary>
        /// CenterX
        /// </summary>
        public int TrackX;
        /// <summary>
        /// CenterY
        /// </summary>
        public int TrackY;
        ///<summary>
        /// Track Direction
        /// </summary>
        public int TrackDirection;
        /// <summary>
        /// Constructor
        /// </summary>
        public BotTracksType(int botNumber, int trackX, int trackY, int trackDirection)
        {
            BotNumber = botNumber;
            TrackX = trackX;
            TrackY = trackY;
            TrackDirection = trackDirection;
        }
        /// <summary>
        /// GetHashCode
        /// </summary>
        public override int GetHashCode()
        {
            return TrackX ^ TrackY ^ TrackDirection;
        }
        /// <summary>
        /// Equals
        /// </summary>
        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (this.GetType() != obj.GetType()) return false;
            // safe because of the GetType check
            BotTracksType  cust = (BotTracksType )obj;
            if (cust.TrackX != TrackX || cust.TrackY != TrackY || cust.TrackDirection != TrackDirection ) return false;
            return true;
        }
        /// <summary>
        /// operator ==
        /// </summary>
        public static bool operator ==(BotTracksType point1, BotTracksType  point2) { return point1.Equals(point2); }
        /// <summary>
        /// operator !=
        /// </summary>
        public static bool operator !=(BotTracksType point1, BotTracksType  point2) { return !point1.Equals(point2); }
    }

}


